package linestrategy

import (
	"codejy/analysis"
	"codejy/analysis/lineanalysis"
	"codejy/globalfunc"
	"codejy/structdef"
	"strings"
)

// 定义策略
type SwitchStrategy struct {
}

// 注册策略
func init() {
	RegisterStrategy(&SwitchStrategy{})
}

// 判断
func (f *SwitchStrategy) getId() int {
	return lineanalysis.Switch
}

// 执行策略  ,这个不能使用指针,需要将值拷贝一份,否则会出现数据错乱其他策略把数据修改了
// 因为在添加数据的时候,是通过指针修改的原始数据,那么假设底层执行了递归并行都调用了这个策略,那么后一个策略的数据就会覆盖前一个策略的数据
func (f SwitchStrategy) Execute(threadStore *structdef.ThreadStore) {
	SwitchHandle(threadStore)
}

func SwitchHandle(threadStore *structdef.ThreadStore) {
	codes := threadStore.Codes
	//获取当前执行指针
	currentPointer := threadStore.CurrentPoint
	length := len(codes)
	for i := currentPointer; i < length; i++ {
		code := codes[i]
		//获取Switch条件表达式的内容
		switchContent := code.LineContent
		//去掉switch关键字
		switchContent = switchContent[6:]
		//获取{位置
		index := strings.Index(switchContent, "{")
		//获取条件表达式
		switchCondition := switchContent[:index]
		//计算条件表达式的值
		switchConditionValue := globalfunc.ExecuteFunc("AssignmentStrategyMode", threadStore, switchCondition).(string)
		//获取switch最后}位置
		end := GetSwitchCodeBlockAllEnd(codes, i+1)
		//找到case符合条件的位置
		for j := i + 1; j < length-1; j++ {
			//判断开头是否是- xx内容
			if IsCaseBlock(codes[j].LineContent) {
				//截取- xx内容
				//1.先去掉-
				caseContent := codes[j].LineContent[1:]
				//2.计算case表达式的值
				caseConditionValue := globalfunc.ExecuteFunc("AssignmentStrategyMode", threadStore, caseContent).(string)
				//3.判断case表达式的值是否等于switch表达式的值
				if caseConditionValue == switchConditionValue {
					//如果相等,则执行case语句块
					endIndex := GetSwitchCodeBlockEnd(codes, j+1)
					//执行case语句块
					LineExecute(threadStore, j+1, endIndex)
					//设置当前执行指针
					threadStore.CurrentPoint = end
					return
				}
				//如果值不相等那么找下一个case的位置
				caseIndex := GetNextCaseIndex(codes, j+1)
				//判断是否是默认语句
				if IsCaseDefaultBlock(codes[caseIndex].LineContent) {
					//如果相等,则执行case语句块
					startIndex := GetNextCaseIndex(codes, j+1)
					//执行case语句块
					LineExecute(threadStore, startIndex+1, end)
					//设置当前执行指针
					threadStore.CurrentPoint = end
					return
				}
				j = GetNextCaseIndex(codes, j+1) - 1
				continue
			}

		}
		//找不到case和default语句块,则直接return
		threadStore.CurrentPoint = end //跳过switch语句块
		return
	}
}

// 获取下一个-的位置
func GetSwitchCodeBlockEnd(codeBlocks []structdef.LineCodeDefinition, startIndex int) int {
	length := len(codeBlocks)
	for i := startIndex; i < length; i++ {
		if strings.HasPrefix(codeBlocks[i].LineContent, "-") {
			return i
		}
	}
	return length

}

// 找到最后一个
func GetSwitchCodeBlockAllEnd(codeBlocks []structdef.LineCodeDefinition, startIndex int) int {
	length := len(codeBlocks)
	var Num = 1
	var j int
	for j = startIndex; j < length; j++ {
		switchBlockCode := codeBlocks[j]
		lineContent := switchBlockCode.LineContent
		//截取语句块的内容
		if strings.HasPrefix(lineContent, "}") {
			Num--
		}
		if Num == 0 {
			break
		}
		if strings.HasSuffix(lineContent, "{") {
			Num++
		}
	}
	return j
}

// 判断是否是case语句块
func IsCaseBlock(lineContent string) bool {
	//判断开头是否是-
	if strings.HasPrefix(lineContent, "-") {
		return true
	}
	return false
}

// 判断是否是case default语句
func IsCaseDefaultBlock(lineContent string) bool {
	//判断开头是否是--
	if strings.HasPrefix(lineContent, "--") {
		return true
	}
	return false
}

// 获取下一个case的位置
func GetNextCaseIndex(codeBlocks []structdef.LineCodeDefinition, startIndex int) int {
	length := len(codeBlocks)
	var j int
	for j = startIndex; j < length; j++ {
		switchBlockCode := codeBlocks[j]
		lineContent := switchBlockCode.LineContent
		if analysis.IsSwitch(lineContent) { //判断是否是switch语句块,如果是那么就跳过
			j = GetSwitchCodeBlockAllEnd(codeBlocks, j+1)
			continue
		}
		//判断是否是case语句块
		if IsCaseBlock(lineContent) {
			break
		}
		//判断是否是默认case
		if IsCaseDefaultBlock(lineContent) {
			break
		}
	}
	return j
}
